home *** CD-ROM | disk | FTP | other *** search
/ MacWorld 2003 August / MW 8 2003 CD1.iso / Inside Macworld / Product News / gimp-1.2.4.sit / gimp-1.2.4 / app / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-17  |  12.8 KB  |  502 lines

  1. /* The GIMP -- an image manipulation program
  2.  * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3.  *
  4.  * This program is free software; you can redistribute it and/or modify
  5.  * it under the terms of the GNU General Public License as published by
  6.  * the Free Software Foundation; either version 2 of the License, or
  7.  * (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17.  */
  18.  
  19. #include "config.h"
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <signal.h>
  24. #include <string.h>
  25. #include <sys/types.h>
  26.  
  27. #ifdef HAVE_SYS_WAIT_H
  28. #include <sys/wait.h>
  29. #endif
  30.  
  31. #ifdef HAVE_UNISTD_H
  32. #include <unistd.h>
  33. #endif
  34.  
  35. #ifndef  WAIT_ANY
  36. #define  WAIT_ANY -1
  37. #endif   /*  WAIT_ANY  */
  38.  
  39. #include <gtk/gtk.h>
  40.  
  41. #include "libgimp/gimpfeatures.h"
  42. #include "libgimp/gimpenv.h"
  43.  
  44. #ifndef  G_OS_WIN32
  45. #include "libgimp/gimpsignal.h"
  46. #endif
  47.  
  48. #include "apptypes.h"
  49.  
  50. #include "appenv.h"
  51. #include "app_procs.h"
  52. #include "errors.h"
  53. #include "user_install.h"
  54.  
  55. #include "libgimp/gimpintl.h"
  56.  
  57. #ifdef G_OS_WIN32
  58. #include <windows.h>
  59. #else
  60. static void   gimp_sigfatal_handler (gint sig_num);
  61. static void   gimp_sigchld_handler  (gint sig_num);
  62. #endif
  63.  
  64. static void   init                  (void);
  65. static void   gimp_error_handler    (const gchar    *domain,
  66.                      GLogLevelFlags  flags,
  67.                      const gchar    *msg,
  68.                      gpointer        user_data);
  69.  
  70. /* GLOBAL data */
  71. gboolean no_interface      = FALSE;
  72. gboolean no_data           = FALSE;
  73. gboolean no_splash         = FALSE;
  74. gboolean no_splash_image   = FALSE;
  75. gboolean be_verbose        = FALSE;
  76. gboolean use_shm           = FALSE;
  77. gboolean use_debug_handler = FALSE;
  78. gboolean console_messages  = FALSE;
  79. gboolean restore_session   = FALSE;
  80. gboolean double_speed      = FALSE;
  81.  
  82. GimpSet *image_context = NULL;
  83.  
  84. MessageHandlerType message_handler = CONSOLE;
  85.  
  86. gchar  *prog_name         = NULL; /* The path name we are invoked with */
  87. gchar  *alternate_gimprc        = NULL;
  88. gchar  *alternate_system_gimprc = NULL;
  89. gchar **batch_cmds              = NULL;
  90.  
  91.  
  92. /* LOCAL data */
  93. static gint    gimp_argc = 0;
  94. static gchar **gimp_argv = NULL;
  95.  
  96. /*
  97.  *  argv processing: 
  98.  *      Arguments are either switches, their associated
  99.  *      values, or image files.  As switches and their
  100.  *      associated values are processed, those slots in
  101.  *      the argv[] array are NULLed. We do this because
  102.  *      unparsed args are treated as images to load on
  103.  *      startup.
  104.  *
  105.  *
  106.  *      The GTK switches are processed first (X switches are
  107.  *      processed here, not by any X routines).  Then the
  108.  *      general GIMP switches are processed.  Any args
  109.  *      left are assumed to be image files the GIMP should
  110.  *      display.
  111.  *
  112.  *      The exception is the batch switch.  When this is
  113.  *      encountered, all remaining args are treated as batch
  114.  *      commands.
  115.  */
  116.  
  117. int
  118. main (int    argc,
  119.       char **argv)
  120. {
  121.   gboolean show_version = FALSE;
  122.   gboolean show_help    = FALSE;
  123.   gint i, j;
  124. #ifdef HAVE_PUTENV
  125.   gchar *display_env;
  126. #endif
  127.  
  128.   g_atexit (g_mem_profile);
  129.  
  130.   /* Initialize variables */
  131.  
  132.   prog_name = argv[0];
  133.  
  134.   /* Initialize i18n support */
  135.   INIT_LOCALE ("gimp");
  136. #if defined (HAVE_BIND_TEXTDOMAIN_CODESET) && defined (GDK_WINDOWING_WIN32)
  137.   bind_textdomain_codeset ("gimp", "UTF-8");
  138. #endif
  139.  
  140. #ifdef ENABLE_NLS
  141.   bindtextdomain ("gimp-libgimp", LOCALEDIR);
  142. #if defined (HAVE_BIND_TEXTDOMAIN_CODESET) && defined (GDK_WINDOWING_WIN32)
  143.   bind_textdomain_codeset ("gimp-libgimp", "UTF-8");
  144. #endif
  145. #endif
  146.  
  147.   gtk_init (&argc, &argv);
  148.  
  149.   setlocale (LC_NUMERIC, "C");  /* gtk seems to zap this during init.. */
  150.  
  151. #ifdef HAVE_PUTENV
  152.   display_env = g_strconcat ("DISPLAY=", gdk_get_display (), NULL);
  153.   putenv (display_env);
  154. #endif
  155.  
  156. #if defined (HAVE_SHM_H) || defined (G_OS_WIN32)
  157.   use_shm = TRUE;
  158. #endif
  159.  
  160.   batch_cmds    = g_new (char *, argc);
  161.   batch_cmds[0] = NULL;
  162.  
  163.   for (i = 1; i < argc; i++)
  164.     {
  165.       if ((strcmp (argv[i], "--no-interface") == 0) ||
  166.       (strcmp (argv[i], "-i") == 0))
  167.     {
  168.       no_interface = TRUE;
  169.        argv[i] = NULL;
  170.     }
  171.       else if ((strcmp (argv[i], "--batch") == 0) ||
  172.            (strcmp (argv[i], "-b") == 0))
  173.     {
  174.       argv[i] = NULL;
  175.       for (j = 0, i++ ; i < argc; j++, i++)
  176.         {
  177.           batch_cmds[j] = argv[i];
  178.           argv[i] = NULL;
  179.         }
  180.       batch_cmds[j] = NULL;
  181.  
  182.       if (batch_cmds[0] == NULL)  /* We need at least one batch command */
  183.         show_help = TRUE;
  184.     }
  185.       else if (strcmp (argv[i], "--system-gimprc") == 0)  
  186.     {
  187.        argv[i] = NULL;
  188.       if (argc <= ++i) 
  189.             {
  190.           show_help = TRUE;
  191.         }
  192.           else 
  193.             {
  194.           alternate_system_gimprc = argv[i];
  195.           argv[i] = NULL;
  196.             }
  197.     } 
  198.       else if ((strcmp (argv[i], "--gimprc") == 0) || 
  199.                (strcmp (argv[i], "-g") == 0))
  200.     {
  201.       argv[i] = NULL;
  202.       if (argc <= ++i) 
  203.             {
  204.           show_help = TRUE;
  205.         }
  206.           else
  207.             {
  208.           alternate_gimprc = argv[i];
  209.           argv[i] = NULL;
  210.             }
  211.     }
  212.       else if ((strcmp (argv[i], "--help") == 0) ||
  213.            (strcmp (argv[i], "-h") == 0))
  214.     {
  215.       show_help = TRUE;
  216.        argv[i] = NULL;
  217.     }
  218.       else if ((strcmp (argv[i], "--version") == 0) ||
  219.                (strcmp (argv[i], "-v") == 0))
  220.     {
  221.       show_version = TRUE;
  222.        argv[i] = NULL;
  223.     }
  224.       else if ((strcmp (argv[i], "--no-data") == 0) ||
  225.            (strcmp (argv[i], "-d") == 0))
  226.     {
  227.       no_data = TRUE;
  228.        argv[i] = NULL;
  229.     }
  230.       else if ((strcmp (argv[i], "--no-splash") == 0) ||
  231.            (strcmp (argv[i], "-s") == 0))
  232.     {
  233.       no_splash = TRUE;
  234.        argv[i] = NULL;
  235.     }
  236.       else if ((strcmp (argv[i], "--no-splash-image") == 0) ||
  237.            (strcmp (argv[i], "-S") == 0))
  238.     {
  239.       no_splash_image = TRUE;
  240.        argv[i] = NULL;
  241.     }
  242.       else if (strcmp (argv[i], "--verbose") == 0)
  243.     {
  244.       be_verbose = TRUE;
  245.        argv[i] = NULL;
  246.     }
  247.       else if (strcmp (argv[i], "--no-shm") == 0)
  248.     {
  249.       use_shm = FALSE;
  250.        argv[i] = NULL;
  251.     }
  252.       else if (strcmp (argv[i], "--debug-handlers") == 0)
  253.     {
  254.       use_debug_handler = TRUE;
  255.        argv[i] = NULL;
  256.     }
  257.       else if ((strcmp (argv[i], "--console-messages") == 0) ||
  258.            (strcmp (argv[i], "-c") == 0))
  259.     {
  260.       console_messages = TRUE;
  261.        argv[i] = NULL;
  262.     }
  263.       else if ((strcmp (argv[i], "--restore-session") == 0) ||
  264.            (strcmp (argv[i], "-r") == 0))
  265.     {
  266.       restore_session = TRUE;
  267.        argv[i] = NULL;
  268.     }
  269.       else if (strcmp (argv[i], "--enable-stack-trace") == 0)  
  270.     {
  271.        argv[i] = NULL;
  272.       if (argc <= ++i) 
  273.             {
  274.           show_help = TRUE;
  275.         }
  276.           else 
  277.             {
  278.           if (! strcmp (argv[i], "never"))
  279.         stack_trace_mode = STACK_TRACE_NEVER;
  280.           else if (! strcmp (argv[i], "query"))
  281.         stack_trace_mode = STACK_TRACE_QUERY;
  282.           else if (! strcmp (argv[i], "always"))
  283.         stack_trace_mode = STACK_TRACE_ALWAYS;
  284.           else
  285.         show_help = TRUE;
  286.  
  287.           argv[i] = NULL;
  288.             }
  289.     }
  290.       /*
  291.        *    ANYTHING ELSE starting with a '-' is an error.
  292.        */
  293.       else if (argv[i][0] == '-')
  294.     {
  295.         g_print (_("\nInvalid option.\n"));
  296.         show_help = TRUE;
  297.     }
  298.     }
  299.  
  300. #ifdef G_OS_WIN32
  301.   /* Common windoze apps don't have a console at all. So does Gimp 
  302.    * - if appropiate. This allows to compile as console application
  303.    * with all it's benfits (like inheriting the console) but hide
  304.    * it, if the user doesn't want it.
  305.    */
  306.   if (!show_help && !show_version && !be_verbose && !console_messages)
  307.     FreeConsole ();
  308. #endif
  309.  
  310.   if (show_version)
  311.     g_print ( "%s %s\n", _("GIMP version"), GIMP_VERSION);
  312.  
  313.   if (show_help)
  314.     {
  315.       g_print (_("\nUsage: %s [option ... ] [file ... ]\n\n"), argv[0]);
  316.       g_print (_("Options:\n"));
  317.       g_print (_("  -b, --batch <commands>   Run in batch mode.\n"));
  318.       g_print (_("  -c, --console-messages   Display warnings to console instead of a dialog box.\n"));
  319.       g_print (_("  -d, --no-data            Do not load brushes, gradients, palettes, patterns.\n"));
  320.       g_print (_("  -i, --no-interface       Run without a user interface.\n"));
  321.       g_print (_("  -g, --gimprc <gimprc>    Use an alternate gimprc file.\n"));
  322.       g_print (_("  -h, --help               Output this help.\n"));
  323.       g_print (_("  -r, --restore-session    Try to restore saved session.\n"));
  324.       g_print (_("  -s, --no-splash          Do not show the startup window.\n"));
  325.       g_print (_("  -S, --no-splash-image    Do not add an image to the startup window.\n"));
  326.       g_print (_("  -v, --version            Output version information.\n"));
  327.       g_print (_("  --verbose                Show startup messages.\n"));      
  328.       g_print (_("  --no-shm                 Do not use shared memory between GIMP and plugins.\n"));
  329.       g_print (_("  --no-xshm                Do not use the X Shared Memory extension.\n"));
  330.       g_print (_("  --debug-handlers         Enable non-fatal debugging signal handlers.\n"));
  331.       g_print (_("  --display <display>      Use the designated X display.\n"));
  332.       g_print (_("  --system-gimprc <gimprc> Use an alternate system gimprc file.\n"));
  333.       g_print ("  --enable-stack-trace <never | query | always>\n");
  334.       g_print (_("                           Debugging mode for fatal signals.\n\n"));
  335.     }
  336.  
  337.   if (show_version || show_help)
  338.     {
  339. #ifdef G_OS_WIN32
  340.       /* Give them time to read the message if it was printed in a
  341.        * separate console window. I would really love to have
  342.        * some way of asking for confirmation to close the console
  343.        * window.
  344.        */
  345.       HANDLE console;
  346.       DWORD mode;
  347.  
  348.       console = GetStdHandle (STD_OUTPUT_HANDLE);
  349.       if (GetConsoleMode (console, &mode) != 0)
  350.     {
  351.       g_print (_("(This console window will close in ten seconds)\n"));
  352.       Sleep(10000);
  353.     }
  354. #endif
  355.       exit (0);
  356.     }
  357.  
  358.   g_log_set_handler ("Gimp",
  359.              G_LOG_LEVEL_MESSAGE,
  360.              gimp_message_func,
  361.              NULL);
  362.  
  363.   /* g_set_message_handler ((GPrintFunc) gimp_message_func); */
  364.  
  365. #ifndef G_OS_WIN32
  366.  
  367.   /* No use catching these on Win32, the user won't get any 
  368.    * stack trace from glib anyhow. It's better to let Windows inform
  369.    * about the program error, and offer debugging (if the user
  370.    * has installed MSVC or some other compiler that knows how to
  371.    * install itself as a handler for program errors).
  372.    */
  373.  
  374.   /* Handle fatal signals */
  375.  
  376.   /* these are handled by gimp_terminate() */
  377.   gimp_signal_private (SIGHUP,  gimp_sigfatal_handler, 0);
  378.   gimp_signal_private (SIGINT,  gimp_sigfatal_handler, 0);
  379.   gimp_signal_private (SIGQUIT, gimp_sigfatal_handler, 0);
  380.   gimp_signal_private (SIGABRT, gimp_sigfatal_handler, 0);
  381.   gimp_signal_private (SIGTERM, gimp_sigfatal_handler, 0);
  382.  
  383.   if (stack_trace_mode != STACK_TRACE_NEVER)
  384.     {
  385.       /* these are handled by gimp_fatal_error() */
  386.       gimp_signal_private (SIGBUS,  gimp_sigfatal_handler, 0);
  387.       gimp_signal_private (SIGSEGV, gimp_sigfatal_handler, 0);
  388.       gimp_signal_private (SIGFPE,  gimp_sigfatal_handler, 0);
  389.     }
  390.  
  391.   /* Ignore SIGPIPE because plug_in.c handles broken pipes */
  392.  
  393.   gimp_signal_private (SIGPIPE, SIG_IGN, 0);
  394.  
  395.   /* Collect dead children */
  396.  
  397.   gimp_signal_private (SIGCHLD, gimp_sigchld_handler, SA_RESTART);
  398.  
  399. #endif /* G_OS_WIN32 */
  400.  
  401.   g_log_set_handler (NULL,
  402.              G_LOG_LEVEL_ERROR | G_LOG_FLAG_FATAL,
  403.              gimp_error_handler,
  404.              NULL);
  405.  
  406.   /* Keep the command line arguments--for use in gimp_init */
  407.   gimp_argc = argc - 1;
  408.   gimp_argv = argv + 1;
  409.  
  410.   /* Check the user_installation */
  411.   user_install_verify (init);
  412.  
  413.   /* Main application loop */
  414.   if (!app_exit_finish_done ())
  415.     gtk_main ();
  416.  
  417.   return 0;
  418. }
  419.  
  420. #ifdef G_OS_WIN32
  421.  
  422. /* In case we build this as a windowed application */
  423.  
  424. #ifdef __GNUC__
  425. #  ifndef _stdcall
  426. #    define _stdcall  __attribute__((stdcall))
  427. #  endif
  428. #endif
  429.  
  430. int _stdcall
  431. WinMain (struct HINSTANCE__ *hInstance,
  432.      struct HINSTANCE__ *hPrevInstance,
  433.      char               *lpszCmdLine,
  434.      int                 nCmdShow)
  435. {
  436.   return main (__argc, __argv);
  437. }
  438.  
  439. #endif
  440.  
  441. static void
  442. init (void)
  443. {
  444.   /*  Continue initializing  */
  445.   gimp_init (gimp_argc, gimp_argv);
  446. }
  447.  
  448.  
  449. static void
  450. gimp_error_handler (const gchar    *domain,
  451.             GLogLevelFlags  flags,
  452.             const gchar    *msg,
  453.             gpointer        user_data)
  454. {
  455.   gimp_fatal_error ("%s", msg);
  456. }
  457.  
  458. #ifndef G_OS_WIN32
  459.  
  460. /* gimp core signal handler for fatal signals */
  461.  
  462. static void
  463. gimp_sigfatal_handler (gint sig_num)
  464. {
  465.   switch (sig_num)
  466.     {
  467.     case SIGHUP:
  468.     case SIGINT:
  469.     case SIGQUIT:
  470.     case SIGABRT:
  471.     case SIGTERM:
  472.       gimp_terminate (g_strsignal (sig_num));
  473.       break;
  474.  
  475.     case SIGBUS:
  476.     case SIGSEGV:
  477.     case SIGFPE:
  478.     default:
  479.       gimp_fatal_error (g_strsignal (sig_num));
  480.       break;
  481.     }
  482. }
  483.  
  484. /* gimp core signal handler for death-of-child signals */
  485.  
  486. static void
  487. gimp_sigchld_handler (gint sig_num)
  488. {
  489.   gint pid;
  490.   gint status;
  491.  
  492.   while (TRUE)
  493.     {
  494.       pid = waitpid (WAIT_ANY, &status, WNOHANG);
  495.  
  496.       if (pid <= 0)
  497.     break;
  498.     }
  499. }
  500.  
  501. #endif /* !G_OS_WIN32 */
  502.